home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / sound / moddis00.zip / mod_dis.c < prev    next >
C/C++ Source or Header  |  1994-03-19  |  33KB  |  1,127 lines

  1. /* BEGIN DAVID LAI COPYRIGHT ********************************************* */
  2. /*
  3. (C) Copyright David Lai 1993, 1994.  All rights reserved.
  4.  
  5. The source code is copyright by David Lai, however it is freely
  6. distributable and released for unrestricted use.  Users may copy or modify 
  7. this source code without charge, provided all copyright
  8. notices remain intact in all the source code.  Portions of the source code
  9. copyright by their respective copyright holders and are covered
  10. under different agreements, however the source code used has
  11. specifically been marked distributable royalty-free.
  12.  
  13. You can do whatever you want with it, even charge money for it, if
  14. you find a sucker willing to pay for it.  This is not shareware, the program
  15. is not crippled in any way, do not send money.  You can e-mail comments
  16. to the electronic mail address below, or fax to the fax number below.
  17.  
  18. If you add a feature thats useful, or do a new port, you can send
  19. the context diffs to the e-mail address below.  I may include it in
  20. subsequent releases.  Your code must specifically be marked
  21. freely distributable, I will not include code marked otherwise.
  22.  
  23. THE SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
  24. THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  25. PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  26.  
  27. The source code is provided with no support and without any obligation on
  28. the part of David Lai to assist in its use, correction,
  29. modification or enhancement.
  30.  
  31. DAVID LAI SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  32. INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
  33. OR ANY PART THEREOF.
  34.  
  35. In no event will David Lai be liable for any lost revenue
  36. or profits or other special, indirect and consequential damages, even if
  37. David Lai has been advised of the possibility of such damages.
  38.  
  39. David Lai
  40. 1370 McKendrie St
  41. San Jose, CA 95126
  42. fax: 408-241-4615
  43.  
  44. lai%fastfood@daver.bungi.com
  45.  
  46. */
  47. /* END   DAVID LAI COPYRIGHT ********************************************* */
  48.  
  49. /* dis-assemble a mod file */
  50.  
  51. #include "misc.h"
  52. #include "modcomp.h"
  53. #include "wav.h"
  54.  
  55. #include "mod_disv.c"    /* some initialized arrays */
  56.  
  57. /* ALLOW_CONTROLS will allow control characters and non-printing characters
  58.    in the name of the mod */
  59. #undef ALLOW_CONTROLS
  60.  
  61. /* RPT_LENGTH_IS_INCR interprets the rpt_length field of samples as 1 more
  62.    than the actual number of words to repeat, for example:
  63.  
  64.     length = 500
  65.     rpt_offset = 0
  66.     rpt_length = 500
  67.  
  68.    The user really meant to say:
  69.  
  70.     length = 500 (998 bytes of real sample)
  71.     rpt_offset = 0 (begin the repeat at the first byte of the real sample)
  72.     rpt_length = 499 (repeat entire 998 bytes of the sample)
  73.  
  74.    Without RPT_LENGTH_IS_INCR, the above will generate warning message that
  75.    there is an attempt to repeat beyond the end of the sample (1000 bytes)
  76. */
  77. #define RPT_LENGTH_IS_INCR
  78.  
  79. static struct sample samples[MAX_INSTRUMENTS];
  80. static int channels=0, instruments=0, num_patterns;
  81. static char mod_tag[MOD_TAGSIZE+1]="";
  82. static char mod_name[MOD_NAME_LENGTH+1];
  83. static int verbose=0;
  84. static int adj, tagsize=MOD_TAGSIZE;
  85. static unsigned char num_patterns_in_song, end_jump_pos;
  86. static unsigned char pattern_table[PATTERN_TABLE_SIZE];
  87. static uint32 file_size;
  88. static int pattern_size;
  89. static off_t fixed_size;
  90. static char *mod_format="mod";
  91. static int file_has_gaps=0;
  92. static int dump_unused_patterns=0;
  93. static uint32 wav_sample_rate=16574;    /* .wav sample rate */
  94.             /* initially set to the middle C rate */
  95. static int wav_info_flag = 1;    /* dump INFO unless requested not to */
  96.  
  97. #define PATTERN_SPACE ((uint32)num_patterns * pattern_size)
  98.  
  99. #ifdef __STDC__
  100. read_tag0(FILE *fi, off_t offset, char tag[MOD_TAGSIZE+1])
  101. #else
  102. read_tag0(fi, offset, tag) FILE *fi; off_t offset; char tag[MOD_TAGSIZE+1];
  103. #endif
  104.  {
  105.  /* read the 4 byte tag at the offset specified and attempt to interpret */
  106.  if (fseek(fi, offset, SEEK_SET)!=0)
  107.     err_exit("Badly formed MOD file: cant seek to tag", NULL);
  108.  if (fread(tag, sizeof(char), MOD_TAGSIZE, fi) != MOD_TAGSIZE)
  109.     err_exit("Badly formed MOD file: cant read tag",NULL);
  110.  tag[MOD_TAGSIZE]='\0';
  111.  if (strcmp(tag,"M.K.")==0 || strcmp(tag,"FLT4")==0 || strcmp(tag,"M!K!")==0 ||
  112.     strcmp(tag,"4CHN")==0 || strcmp(tag,"M&K!")==0 )
  113.     {
  114.     channels = 4;
  115.     return 1; /* success */
  116.     }
  117.  else if (strcmp(tag,"6CHN")==0)
  118.     {
  119.     channels = 6;
  120.     return 1; /* success */
  121.     }
  122.  else if (strcmp(tag,"8CHN")==0 || strcmp(tag,"OCTA")==0)
  123.     {
  124.     channels = 8;
  125.     return 1; /* success */
  126.     }
  127.  else
  128.     return 0; /* dont know this tag */
  129.  }
  130.  
  131. #ifdef __STDC__
  132. read_tag(FILE *fi)
  133. #else
  134. read_tag(fi) FILE *fi;
  135. #endif
  136.  {
  137.  /* read and interpret tag to determine file format */
  138.  char tag[MOD_TAGSIZE+1], tag15[MOD_TAGSIZE+1];
  139.  /* check if it is a 31 instr file first */
  140.  if (read_tag0(fi, TAG_OFFSET_31, tag)==1)
  141.   {
  142.   instruments = 31;
  143.   strcpy(mod_tag, tag);
  144.   return 1;
  145.   }
  146.  /* try again with 15 instr */
  147.  if (read_tag0(fi, TAG_OFFSET_15, tag15)==1)
  148.   {
  149.   instruments = 15;
  150.   strcpy(mod_tag, tag15);
  151.   return 1;
  152.   }
  153.  /* take a guess that it is 4 track */
  154.     if (verbose) fprintf(stderr, "Warning: Unknown tag 31=%s 15=%s\n", tag, tag15);
  155.     fprintf(stderr,"Unknown mod format - assuming -c 4 -i 15\n");
  156.     channels = 4;
  157.     instruments = 15;
  158.     tagsize = 0;
  159. #if 0
  160.     {
  161.     int c;
  162.     /* check if there is printable chars at location 470 */
  163.     if (fseek(fi, CHECK_31_INST_OFFSET, SEEK_SET)!=0)
  164.         err_exit("Unable to seek to check", NULL);
  165.     c=getc(fi);
  166.     if (isascii(c) && isprint(c))    /* this test may not work all the time */
  167.         {
  168.         instruments = 31;
  169.           strcpy(mod_tag, tag15);
  170.         }
  171.     else
  172.         {
  173.         instruments= 15;
  174.           strcpy(mod_tag, tag15);
  175.         }
  176.     }
  177. #endif
  178.  return 1;
  179.  }
  180.  
  181. void
  182. #ifdef __STDC__
  183. verify_format(FILE *fi)
  184. #else
  185. verify_format(fi) FILE *fi;
  186. #endif
  187.  {
  188.  /* verify the name of the mod is valid */
  189.  int i,j;
  190.  uint32 total_sample_size;
  191.  if (fseek(fi, 0L, SEEK_SET)!=0)
  192.     err_exit("Badly formed MOD file", NULL);
  193.  if(fread(mod_name, sizeof(char), MOD_NAME_LENGTH, fi) != MOD_NAME_LENGTH)
  194.     err_exit("Badly formed MOD file - mod name", NULL);
  195.  mod_name[MOD_NAME_LENGTH]='\0';
  196.  /* check all chars are valid */
  197.  for (i=0; i< MOD_NAME_LENGTH; i++) 
  198.     if ((!isascii(mod_name[i])) || (!isprint(mod_name[i]) && mod_name[i]!='\0'))
  199. #ifndef ALLOW_CONTROLS
  200.         err_exit("Bad mod name, character 0x%x",(unsigned char)mod_name[i]);
  201. #else
  202.         fprintf(stderr, "Bad mod name, character 0x%x\n",(unsigned char)mod_name[i]);
  203. #endif
  204.  /* verify that all sample headers are OK */
  205.  for (j=0; j< instruments; j++)
  206.     {
  207.      if (fseek(fi, SAMPLE_HEADER_OFFSET + 
  208.         SAMPLE_HEADER_LENGTH *j, SEEK_SET)!=0)
  209.         err_exit("Badly formed MOD file, cant read sample headers", NULL);
  210.      if (fread( samples[j].name, sizeof(char), SAMPLE_NAME_SIZE, fi) != 
  211.         SAMPLE_NAME_SIZE)
  212.             err_exit("Cant read sample name %d",j);
  213.     samples[j].name[SAMPLE_NAME_SIZE]='\0';
  214.     if (verbose > 1)
  215.      {
  216.      for(i=0; samples[j].name[i]!='\0' && i< SAMPLE_NAME_SIZE; i++)
  217.         if (!isprint(samples[j].name[i]) && isascii(samples[j].name[i]))
  218.             fprintf(stderr,"Warning: Bad character in sample #%d name, character 0x%x in %s\n",
  219.               j, (unsigned char)samples[j].name[i], samples[j].name);
  220.      }
  221.     samples[j].length = rbshort(fi);
  222.     samples[j].orig_length = samples[j].length;
  223.     if (samples[j].length == (SAMPLE_IGNORE_BYTES / 2)) 
  224.         {
  225.         if (verbose > 1) 
  226.             fprintf(stderr,"Warning: zeroing sample %d length (was %u)\n",
  227.              j,samples[j].length);
  228.         samples[j].length = 0;
  229.         adj+= (SAMPLE_IGNORE_BYTES / 2); 
  230.              /* adjustment for filelength checks */
  231.         }
  232.     if (fread( &samples[j].finetune, 1, 1, fi)!=1)
  233.         err_exit("Cant read sample %d's finetune", j);
  234.     /* sign extend finetune */
  235.     samples[j].finetune = SIGN_EXT_NIBBLE(samples[j].finetune);
  236.     if (fread( &samples[j].volume, 1, 1, fi)!=1)
  237.         err_exit("Cant read sample %d's volume", j);
  238.     if (samples[j].volume > 64)
  239.         {
  240.         if (verbose)
  241.             fprintf(stderr,"Warning: volume for sample %d out of range %d, set to 64\n",j, samples[j].volume);
  242.         samples[j].volume = 64;
  243.         }
  244.     samples[j].rpt_offset = rbshort(fi);
  245.     samples[j].rpt_leng